from ...pao_python.pao.data import get_string_to_date, get_date, get_first_last_day_month, DataProcess, process_db, dataframe_to_list, DataList, string_to_date, string_to_date_only
from ...pao_python.pao.service.data.mongo_db import MongoService, MongoFilter, C, N, F, as_date
from ...pao_python.pao.commom import get_data
from ...service.buss_pub.bill_manage import BillManageService, OperationType, TypeId, Status
from ...service.mongo_bill_service import MongoBillFilter
from ...service.common import insert_data, find_data, update_data, delete_data, get_condition, get_info, get_current_user_id, get_current_organization_id, operation_result, rang_time
from ...pao_python.pao.remote import JsonRpc2Error
from ...service.buss_mis.service_operation import ServiceOperationService
from ...service.welfare_institution.accommodation_process import AccommodationProcess
import pandas as pd


class CostManageService(MongoService):
    def __init__(self, db_addr, db_port, db_name, db_user, db_pwd, inital_password, session):
        DataProcess.__init__(self, db_addr, db_port, db_name, db_user, db_pwd)
        self.inital_password = inital_password
        self.session = session
        self.bill_manage_service = BillManageService(
            db_addr, db_port, db_name, db_user, db_pwd, inital_password, session)
        self.service_operation_func = ServiceOperationService(
            db_addr, db_port, db_name, db_user, db_pwd, inital_password, session)
        self.accommodation_process = AccommodationProcess(
            db_addr, db_port, db_name, db_user, db_pwd, inital_password, session)

    def get_incidental_list(self, org_list, condition, page, count, table_name='PT_Incidental_Cost'):
        # 获取杂费记录
        _filter = MongoBillFilter()
        keys = ['id', 'name']
        if 'time_range' in condition.keys():
            start_date = as_date(condition['time_range'][0])
            end_date = as_date(condition['time_range'][1])
            _filter = rang_time(_filter, start_date, end_date)
        values = self.get_value(condition, keys)
        _filter.match_bill((C('id') == values['id']) & (C('organization_id').inner(org_list))) \
            .lookup_bill('PT_User', 'user_id', 'id', 'user') \
               .add_fields({'name': '$user.name'}) \
               .match(C('name').like(values['name']))\
               .sort({'modify_date': -1})\
            .project({'_id': 0, 'user._id': 0})
        res = self.page_query(_filter, table_name, page, count)
        return res

    def update_incidental(self, data, config, isImport=None):
        '''
            data    杂费/伙食费数据
            config  {name:'杂费',table_name:'表名'}
        '''
        # 更新或增加杂费记录

        data['start_date'] = string_to_date_only(
            data['start_date'].split('T')[0]) if 'T' in data['start_date'] else string_to_date_only(data['start_date'])
        data['end_date'] = string_to_date_only(data['end_date'].split('T')[0]) if 'T' in data['end_date'] else string_to_date_only(
            data['end_date'])
        data['operator_id'] = get_current_user_id(self.session)
        hasId = data.get('id')  # 是否新增
        data = get_info(data, self.session)
        flag = OperationType.update.value if hasId else OperationType.add.value
        # 查找该长者订单
        _filter = MongoBillFilter()
        _filter.match_bill((C('state') == '居住中') & (C('user_id') == data['user_id'])) \
            .inner_join_bill('PT_Service_Order', 'order_id', 'id', 'order')
        res = self.query(_filter, 'IEC_Check_In')
        if not len(res):
            raise JsonRpc2Error(-36102, '找不到该长者入住订单')
        order_id = res[0]['order']['id']
        # 获取生成服务记录的参数
        recode_param = self.accommodation_process.get_item_info(
            config['name'], order_id, {'总费用': data['money']})[0]
        recode_param.update(
            start_date=data['start_date'], end_date=data['end_date'])
        data.update(start_date=data['start_date'], end_date=data['end_date'])
        service_recode = {}
        if hasId:
            _filter_recode = MongoBillFilter()
            _filter_recode.match_bill(C('id') == data['id'])
            res_cost = self.query(_filter_recode, config['table_name'])
            if len(res_cost):
                recode_id = res_cost[0]['recode_id']
                service_recode = self.service_operation_func.add_service_record(
                    order_id, recode_param['service_product_id'], '0', other=recode_param, is_update=recode_id)
        else:
            service_recode = self.service_operation_func.add_service_record(
                order_id, recode_param['service_product_id'], '0', other=recode_param)
            data.update(recode_id=service_recode['id'])
        if isImport:
            return {'data': data, 'recode': service_recode}
        else:
            bill_id = self.bill_manage_service.add_bill(flag, config['type'], [
                                                        data, service_recode], [config['table_name'], 'PT_Service_Record'])
            return operation_result(bill_id)

    def delete_incidental(self, ids, table_name='PT_Incidental_Cost', TypeId=''):
        '''删除杂费'''
        bill_id = False
        for service_scope_id in ids:
            # 查询被删除的数据信息
            _filter = MongoBillFilter()
            _filter.match_bill(C('id') == service_scope_id) \
                .inner_join_bill('PT_Service_Record', 'recode_id', 'id', 'recode') \
                .match(C('recode.cost_status') == None)
            res = self.query(_filter, table_name)
            if len(res):
                bill_id = self.bill_manage_service.add_bill(OperationType.delete.value,
                                                            TypeId, [[{'id': res[0]['id']}], [{'id': res[0]['recode_id']}]], [table_name, 'PT_Service_Record'])
            else:
                raise JsonRpc2Error(-36105, '该费用已生成账单或不存在,不能删除')
        return operation_result(bill_id)

    def get_food_cost_list(self, org_list, condition, page, count):
        # 获取餐费记录
        _filter = MongoBillFilter()
        keys = ['id', 'name']
        values = self.get_value(condition, keys)
        _filter.match_bill((C('id') == values['id']) & (C('organization_id').inner(org_list))) \
               .lookup_bill('PT_User', 'user_id', 'id', 'user') \
               .add_fields({'name': '$user.name'}) \
               .match(C('name').like(values['name']))\
            .project({'_id': 0})
        res = self.page_query(_filter, 'PT_Food_Cost', page, count)
        return res

    def get_medical_cost_list(self, org_list, condition, page, count):
        # 获取医疗费用记录
        _filter = MongoBillFilter()
        keys = ['id']
        values = self.get_value(condition, keys)
        _filter.match_bill((C('id') == values['id']) & (C('organization_id').inner(org_list)))\
            .project({'_id': 0})
        res = self.page_query(_filter, 'PT_Medical_Cost', page, count)
        return res

    def update_medical_cost(self, data):
        # 更新或增加医疗费用记录
        res = 'Fail'
        data['operator_id'] = get_current_user_id(self.session)

        def process_func(db):
            nonlocal res
            if 'id' in data.keys():
                bill_id = self.bill_manage_service.add_bill(OperationType.update.value,
                                                            TypeId.diaperCost.value, data, 'PT_Medical_Cost')
                if bill_id:
                    res = 'Success'
            else:
                bill_id = self.bill_manage_service.add_bill(OperationType.add.value,
                                                            TypeId.diaperCost.value, data, 'PT_Medical_Cost')
                self.bill_manage_service.add_bill(OperationType.add.value,
                                                  TypeId.diaperCost.value, data, 'PT_Service_Record')
                if bill_id:
                    res = 'Success'
        process_db(self.db_addr, self.db_port, self.db_name,
                   process_func, self.db_user, self.db_pwd)
        return res

    def delete_medical_cost(self, ids):
        '''删除医疗费用'''
        res = 'fail'

        def process_func(db):
            nonlocal res
            for service_scope_id in ids:
                # 查询被删除的数据信息
                data = find_data(db, 'PT_Medical_Cost', {
                    'id': service_scope_id, 'bill_status': Status.bill_valid.value})
                if len(data) > 0:
                    self.bill_manage_service.add_bill(OperationType.delete.value,
                                                      TypeId.serviceProduct.value, data[0], 'PT_Medical_Cost')
            res = 'Success'
        process_db(self.db_addr, self.db_port, self.db_name,
                   process_func, self.db_user, self.db_pwd)
        return res

    def get_diaper_cost_list(self, condition, page, count):
        # 获取尿片费用记录
        _filter = MongoBillFilter()
        keys = ['id']
        values = self.get_value(condition, keys)
        _filter.match_bill(C('id') == values['id'])\
            .project({'_id': 0})
        res = self.page_query(_filter, 'PT_Diaper_Cost', page, count)
        return res

    def update_diaper_cost(self, data):
        # 更新或增加尿片费用记录
        res = 'Fail'
        data['operator_id'] = get_current_user_id(self.session)

        def process_func(db):
            nonlocal res
            if 'id' in data.keys():
                bill_id = self.bill_manage_service.add_bill(OperationType.update.value,
                                                            TypeId.diaperCost.value, data, 'PT_Diaper_Cost')
                if bill_id:
                    res = 'Success'
            else:
                bill_id = self.bill_manage_service.add_bill(OperationType.add.value,
                                                            TypeId.diaperCost.value, data, 'PT_Diaper_Cost')
                self.bill_manage_service.add_bill(OperationType.add.value,
                                                  TypeId.diaperCost.value, data, 'PT_Service_Record')
                if bill_id:
                    res = 'Success'
        process_db(self.db_addr, self.db_port, self.db_name,
                   process_func, self.db_user, self.db_pwd)
        return res

    def delete_diaper_cost(self, ids):
        '''删除尿片费用'''
        res = 'fail'

        def process_func(db):
            nonlocal res
            for service_scope_id in ids:
                # 查询被删除的数据信息
                data = find_data(db, 'PT_Diaper_Cost', {
                    'id': service_scope_id, 'bill_status': Status.bill_valid.value})
                if len(data) > 0:
                    self.bill_manage_service.add_bill(OperationType.delete.value,
                                                      TypeId.serviceProduct.value, data[0], 'PT_Diaper_Cost')
            res = 'Success'
        process_db(self.db_addr, self.db_port, self.db_name,
                   process_func, self.db_user, self.db_pwd)
        return res

    def upload_incidental(self, data, config, TypeId):
        condition = self.__get_data_param(data, config)
        bill_id = self.bill_manage_service.add_bill(OperationType.add.value, TypeId, condition, [
                                                    config['table_name'], 'PT_Service_Record'])
        return '导入成功' if bill_id else '导入失败'

    def __get_data_param(self, data, config):
        pf = pd.DataFrame(data)
        pf.rename(columns={'长者': 'name', '身份证': 'id_card', '开始时间': 'start_date',
                           '结束时间': 'end_date', '费用': 'money'}, inplace=True)
        id_cards = pf['id_card'].values.tolist()
        _filter = MongoBillFilter()
        _filter.match_bill(C('id_card').inner(id_cards)) \
               .project({'id': 1, 'name': 1, 'id_card': 1, '_id': 0})
        res = self.query(_filter, 'PT_User')
        user_pf = pd.DataFrame(res)
        new_pf = pd.merge(pf, user_pf, on=['name', 'id_card'])
        new_pf.rename(columns={'id': 'user_id'}, inplace=True)
        if len(new_pf.index) != len(pf.index):
            raise JsonRpc2Error(-36101, '长者信息有误，请仔细检查')
        new_pf = new_pf.drop(['id_card'], axis=1)
        condition = dataframe_to_list(new_pf)
        recode = []
        data_new = []
        for i, x in enumerate(condition):
            cur_name = x['name']
            del x['name']
            if (x['start_date'] and x['end_date']):
                try:
                    incidental = self.update_incidental(
                        condition[i], config, True)
                    recode.append(incidental['recode'])
                    data_new.append(incidental['data'])
                except:
                    raise JsonRpc2Error(-36105, '找不到' +
                                        cur_name+'的入住订单或者开始/结束时间已存在')
            else:
                raise JsonRpc2Error(-36102, '请确保开始时间和结束时间填写完整')
        return [data_new, recode]

    def export_template(self, org_list):
        _filter = MongoBillFilter()
        _filter.match_bill(
            (C('organization_id').inner(org_list))
            & (C('state') == '居住中'))\
            .inner_join_bill('PT_User', 'user_id', 'id', 'user')\
            .add_fields({
                '身份证': '$user.id_card',
                '长者': '$user.name',
                '开始时间': '',
                '结束时间': '',
                '费用': '',
            })\
            .project({'_id': 0, '长者': 1, '身份证': 1, '开始时间': 1, '结束时间': 1, '费用': 1})
        res = self.query(_filter, 'IEC_Check_In')
        # print(res)
        return res
